/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package TweetRay;

import Raytracing.Shaders.Shader;
import Raytracing.Geometry.Triangle;
import java.util.ArrayList;
import processing.core.PApplet;
import processing.core.PGraphics3D;
import processing.core.PVector;

/**
 *
 *           __
 *          /  \
 *          ^  ^
 *         / \/ \
 *         | .| .|
 *         \_/\_/
 *          |  |
 *          \ o/
 *          /  \
 *         |    |
 *         | | ||
 *         | 0 0|
 *         |    |
 */
public class DiscLight extends Entity implements Light, Traceable {

    PVector[] pts = new PVector[5];
    Shader[] shaders = null;
    int shaderIndex;
    private PVector forward, up, right;
    Triangle tri1, tri2;

    public DiscLight(float x, float y, float z, float tx, float ty, float tz, Shader[] shaders, int shaderIndex) {
        super(x, y, z);

        PVector globalUp = new PVector(0, 1, 0);
        forward = new PVector(tx, ty, tz);
        float mag = forward.mag();
        forward.normalize();

        right = PVector.cross(forward, globalUp, null);
        right.normalize();

        up = PVector.cross(forward, right, null);
        up.normalize();
        right.mult(mag / 2);
        up.mult(mag / 2);

        pts[1] = new PVector(x + tx, y + ty, z + tz);


        pts[0] = new PVector(x, y, z);
        pts[0].add(up);
        pts[0].sub(right);

        pts[2] = new PVector(x, y, z);
        pts[2].add(up);
        pts[2].add(right);

        pts[3] = new PVector(x, y, z);
        pts[3].sub(up);
        pts[3].add(right);

        pts[4] = new PVector(x, y, z);
        pts[4].sub(up);
        pts[4].sub(right);





        this.shaders = shaders;
        this.shaderIndex = shaderIndex;
    }

    @Override
    public void draw(PGraphics3D p3d) {
        p3d.pushMatrix();
        p3d.fill(255);

        p3d.beginShape(PApplet.QUADS);
        p3d.vertex(pts[0].x, pts[0].y, pts[0].z);

        p3d.vertex(pts[2].x, pts[2].y, pts[2].z);
        p3d.vertex(pts[3].x, pts[3].y, pts[3].z);
        p3d.vertex(pts[4].x, pts[4].y, pts[4].z);
        p3d.endShape();
        p3d.popMatrix();
    }

    public PVector getNormal() {
        return forward;
    }

    public void rotate(PVector origin, PVector direction, float amt) {
        super.rotate(origin, direction, amt);
        for (int i = 0; i < pts.length; i++) {
            pts[i].rotate(origin, direction, amt);
        }
        forward.x = pts[1].x - pts[0].x;
        forward.y = pts[1].y - pts[0].y;
        forward.z = pts[1].z - pts[0].z;
        forward.normalize();
        up.x = pts[2].x - pts[0].x;
        up.y = pts[2].y - pts[0].y;
        up.z = pts[2].z - pts[0].z;

        right.x = pts[4].x - pts[0].x;
        right.y = pts[4].y - pts[0].y;
        right.z = pts[4].z - pts[0].z;
    }

    @Override
    public void pack(UTFWriter output) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public void scale(int axis, float amt) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public void translate(PVector dir) {

        if (tx + dir.x < 255 && tx + dir.x > 0) {

            tx += dir.x;
            for (int i = 0; i < pts.length; i++) {
                pts[i].x += dir.x;
            }
        }

        if (ty + dir.y < 255 && ty + dir.y > 0) {

            ty += dir.y;
            for (int i = 0; i < pts.length; i++) {
                pts[i].y += dir.y;
            }
        }

        if (tz + dir.z < 255 && tz + dir.z > 0) {

            tz += dir.z;
            for (int i = 0; i < pts.length; i++) {
                pts[i].z += dir.z;
            }
        }


    }

    @Override
    public Entity copy() {
        return null;
    }

    public PVector getSample() {
        float a = (float) Math.random();
        float b = (float) Math.random();

        PVector toRet = new PVector(tx, ty, tz);

        toRet.add(up.x * a, up.y * a, up.z * a);
        toRet.add(right.x * b, right.y * b, right.z * b);

        return toRet;
    }

    public ArrayList tesselate() {
        ArrayList toRet = new ArrayList();

        tri1 = new Triangle(shaders[shaderIndex], pts[0], pts[2], pts[3], 0, 0, 0, 0f, 0, 0f, null);
        tri2 = new Triangle(shaders[shaderIndex], pts[3], pts[4], pts[0], 0, 0, 0, 0f, 0, 0f, null);
        toRet.add(tri1);
        toRet.add(tri2);
        return toRet;


    }

    public float getArea() {
        return (tri1.area + tri2.area);
    }

    public void getEmit(PVector in) {
        in.mult(shaders[shaderIndex].emit);
    }

    public void setShader(int shaderIndex) {

        this.shaderIndex = shaderIndex;
        tesselate();

    }

    public void pickDraw(PGraphics3D p3d, int index) {
    }
}
